home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / src / hotlist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  8.2 KB  |  352 lines

  1. /* Directory hotlist -- for the Midnight Commander
  2.    Copyright (C) 1994 Radek Doulik
  3.    Copyright (C) 1995 Janne Kukonlehto
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2 of the License, or
  8.    (at your option) any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  18.  */
  19.  
  20. #include <config.h>
  21. #ifdef HAVE_UNISTD_H
  22. #   include <unistd.h>
  23. #endif
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>        /* For malloc() */
  27. #include <sys/types.h>
  28. #include <sys/param.h>
  29. #include <sys/stat.h>
  30. #include <grp.h>
  31. #include <pwd.h>
  32. #include "tty.h"
  33. #include "mad.h"
  34. #include "util.h"        /* Needed for the externs */
  35. #include "win.h"
  36. #include "color.h"
  37. #include "dlg.h"
  38. #include "widget.h"
  39. #include "dialog.h"        /* For do_refresh() */
  40. #include "setup.h"        /* For profile_bname */
  41. #include "profile.h"        /* Load/save directories hotlist */
  42.  
  43. #include "../vfs/vfs.h"
  44. /* Needed for the extern declarations of integer parameters */
  45. #include "dir.h"
  46. #include "panel.h"        /* Needed for the externs */
  47. #include "file.h"
  48. #include "main.h"
  49. #include "global.h"
  50. #include "hotlist.h"
  51.  
  52. #define UX        5
  53. #define UY        2
  54.  
  55. #define BX        5
  56. #define BY        18
  57.  
  58. #define BUTTONS        4
  59. #define LABELS          3
  60. #define B_ADD        B_USER
  61. #define B_REMOVE        B_USER + 1
  62.  
  63. static WListbox *l_hotlist;
  64.  
  65. static Dlg_head *hotlist_dlg;
  66.  
  67. static WLabel *pname;
  68.  
  69. static char *hotlist_section = "Hotlist";
  70.  
  71. struct {
  72.     int ret_cmd, y, x;
  73.     char *text;
  74.     int hkey, hpos;
  75. } hotlist_but[BUTTONS] = {
  76.     { B_CANCEL, 0, 53, "[ Cancel ]",  'c', 2, },
  77.     { B_ADD,    0, 25, "[ Add new ]", 'a', 2, },
  78.     { B_REMOVE, 0, 13, "[ Remove ]",  'r', 2, },
  79.     { B_ENTER,  0,  0, "[[ Chdir ]]", 'd', 5, },
  80. };
  81.  
  82. struct {
  83.     int y, x;
  84.     char *text;
  85. } hotlist_text [LABELS] = {
  86.     { UY, UX + 1, " Directory label " },
  87.     { UY+12, UX+1, " Directory path "},
  88.     { UY+13, UX+2, "" },
  89. };
  90.  
  91. /* Directory hotlist */
  92. static struct hotlist{
  93.     char *directory;
  94.     char *label;
  95.     struct hotlist *next;
  96. } *hotlist = NULL;
  97.  
  98. #ifndef HAVE_X
  99. static void hotlist_refresh (void)
  100. {
  101.     attrset (REVERSE_COLOR);
  102.     dlg_erase (hotlist_dlg);
  103.     
  104.     draw_box (hotlist_dlg, 1, 2, 20, 70);
  105.     draw_box (hotlist_dlg, UY, UX, 12, 63);
  106.     draw_box (hotlist_dlg, UY + 12, UX, 3, 63);
  107. }
  108. #endif
  109.  
  110. /* If current->data is 0, then we are dealing with a VFS pathname */
  111. static INLINE void update_path_name ()
  112. {
  113.     char *text;
  114.  
  115.     if (!l_hotlist->current)
  116.     return;
  117.     
  118.     if (l_hotlist->current->data != 0)
  119.     text = ((struct hotlist *)l_hotlist->current->data)->directory;
  120.     else {
  121.     text = l_hotlist->current->text;
  122.     }
  123.     label_set_text (pname, name_trunc (text, 59));
  124. }
  125.  
  126. static int hotlist_callback (Dlg_head * h, int Par, int Msg)
  127. {
  128.     switch (Msg) {
  129. #ifndef HAVE_X    
  130.     case DLG_DRAW:
  131.     hotlist_refresh ();
  132.     break;
  133. #endif    
  134.  
  135.     case DLG_POST_KEY:
  136.     /* fall */
  137.     case DLG_INIT:
  138.     attrset (MENU_ENTRY_COLOR);
  139.     update_path_name ();
  140.     break;
  141.     }
  142.     return 0;
  143. }
  144.  
  145. static int l_call (void *data)
  146. {
  147.     return 1;
  148. }
  149.  
  150. static void add_name_to_list (char *path)
  151. {
  152.     listbox_add_item (l_hotlist, 0, 0, path, 0);
  153. }
  154.  
  155. static void init_hotlist (int is_vfs_list)
  156. {
  157.     int i;
  158.     struct hotlist *current = hotlist;
  159.  
  160.     do_refresh ();
  161.  
  162.     hotlist_dlg = create_dlg (0, 0, 22, 74, dialog_colors,
  163.                   hotlist_callback, "[Hotlist]",
  164.                   is_vfs_list ? "vfshot":"hotlist",
  165.                   DLG_CENTER);
  166.     x_set_dialog_title (hotlist_dlg,
  167.         is_vfs_list ? "Active VFS directories":"Directory hotlist");
  168.  
  169. #define XTRACT(i) BY+hotlist_but[i].y, BX+hotlist_but[i].x, hotlist_but[i].ret_cmd, hotlist_but[i].text, hotlist_but[i].hkey, hotlist_but[i].hpos, 0, 0
  170.  
  171.     for (i = 0; i < BUTTONS; i++){
  172.     if (is_vfs_list && (i == 1 || i == 2))
  173.         continue;
  174.     add_widgetl (hotlist_dlg, button_new (XTRACT (i)), (i == BUTTONS - 1) ?
  175.         XV_WLAY_CENTERROW : XV_WLAY_RIGHTOF);
  176.     }
  177.  
  178.     /* We add the labels.  We are interested in the last one,
  179.      * that one will hold the path name label
  180.      */
  181.     for (i = 0; i < LABELS; i++){
  182.     pname = label_new (hotlist_text [i].y,
  183.                hotlist_text [i].x, hotlist_text [i].text);
  184.     add_widget (hotlist_dlg, pname);
  185.     }
  186.     /* get new listbox */
  187.     l_hotlist = listbox_new (UY + 1, UX + 1, 61, 10, 0, l_call);
  188.  
  189.     /* Fill the hotlist with the active VFS or the hotlist */
  190.     if (is_vfs_list){
  191.     listbox_add_item (l_hotlist, 0, 0, home_dir, 0);
  192.     vfs_fill_names (add_name_to_list);
  193.     } else
  194.     while (current){
  195.         listbox_add_item (l_hotlist, 0, 0, current->label, current);
  196.         current = current->next;
  197.     }
  198.  
  199.     add_widgetl (hotlist_dlg, l_hotlist, XV_WLAY_EXTENDWIDTH); 
  200.     /* add listbox to the dialogs */
  201. }
  202.  
  203. static void hotlist_done (void)
  204. {
  205.     destroy_dlg (hotlist_dlg);
  206.     if (0)
  207.     update_panels (UP_OPTIMIZE, UP_KEEPSEL, UP_KEEPSEL);
  208.     repaint_screen ();
  209. }
  210.  
  211. static void add2hotlist (char *label, char *directory)
  212. {
  213.     struct hotlist *current, *old;
  214.  
  215.     old = NULL;
  216.     current = hotlist;
  217.     while (current && strcmp (current->label, label) <= 0){
  218.     old = current;
  219.     current = current->next;
  220.     }
  221.  
  222.     if (old == NULL){
  223.     hotlist = malloc (sizeof (struct hotlist));
  224.     hotlist->label = label;
  225.     hotlist->directory = directory;
  226.     hotlist->next = current;
  227.     } else {
  228.     struct hotlist *new;
  229.     new = malloc (sizeof (struct hotlist));
  230.     new->label = label;
  231.     new->directory = directory;
  232.     old->next = new;
  233.     new->next = current;
  234.     }
  235. }
  236.  
  237. void add2hotlist_cmd (void)
  238. {
  239.     char *prompt, *label;
  240.  
  241.     prompt = malloc (strlen (cpanel->cwd) + 20);
  242.     sprintf (prompt, "Label for \"%s\":", cpanel->cwd);
  243.     label = input_dialog (" Add to hotlist ", prompt, "");
  244.     free (prompt);
  245.     if (!label || !*label)
  246.     return;
  247.  
  248.     add2hotlist (label, strdup (cpanel->cwd));
  249. }
  250.  
  251. static void remove_from_hotlist (struct hotlist *entry)
  252. {
  253.     if (entry == hotlist){
  254.     hotlist = hotlist->next;
  255.     } else {
  256.     struct hotlist *current = hotlist;
  257.     while (current && current->next != entry)
  258.         current = current->next;
  259.     if (current){
  260.         current->next = entry->next;
  261.     }
  262.     }
  263.     
  264.     /* FIXME: Commented out because freeing seems to cause corruption
  265.        after some add and remove operations */
  266.     /*free (entry->label);
  267.     free (entry->directory);
  268.     free (entry);*/
  269. }
  270.  
  271. char *hotlist_cmd (int vfs_or_hotlist)
  272. {
  273.     char *target = NULL;
  274.  
  275.     init_hotlist (vfs_or_hotlist);
  276.  
  277.     /* display file info */
  278.     attrset (SELECTED_COLOR);
  279.  
  280.     run_dlg (hotlist_dlg);
  281.  
  282.     switch (hotlist_dlg->ret_value) {
  283.     case B_CANCEL:
  284.     break;
  285.  
  286.     case B_ADD:
  287.     add2hotlist_cmd ();
  288.     break;
  289.  
  290.     case B_REMOVE:
  291.     remove_from_hotlist (l_hotlist->current->data);
  292.     break;
  293.  
  294.     case B_ENTER:
  295.     if (l_hotlist->current->data)
  296.         target = ((struct hotlist*) l_hotlist->current->data) -> directory;
  297.     else
  298.         target = strdup (l_hotlist->current->text);
  299.     break;
  300.     }
  301.  
  302.     hotlist_done ();
  303.     return target;
  304. }
  305.  
  306. void load_hotlist (void)
  307. {
  308.     void *profile_keys;
  309.     char *key, *value;
  310.     
  311.     profile_keys = profile_init_iterator (hotlist_section, profile_name);
  312.  
  313.     if (!profile_keys){
  314.     add2hotlist (strdup ("Home directory"), strdup (home_dir));
  315.     add2hotlist (strdup ("Root directory"), strdup (PATH_SEP_STR));
  316.     return;
  317.     }
  318.     
  319.     while (profile_keys){
  320.     profile_keys = profile_iterator_next (profile_keys, &key, &value);
  321.     add2hotlist (strdup (value), strdup (key));
  322.     }
  323. }
  324.  
  325. void save_hotlist (void)
  326. {
  327.     struct hotlist *current = hotlist;
  328.     
  329.     profile_clean_section (hotlist_section, profile_name);
  330.     for (;current; current = current->next){
  331.     WritePrivateProfileString (hotlist_section,
  332.                    current->directory,
  333.                    current->label,
  334.                    profile_name);
  335.     }
  336.     /* So that maybe later setup is not saved if not asked to */
  337.     sync_profiles ();
  338. }
  339.  
  340. void done_hotlist (void)
  341. {
  342.     struct hotlist *current = hotlist;
  343.     struct hotlist *next;
  344.  
  345.     for (; current; current = next){
  346.     next = current->next;
  347.     free (current->label);
  348.     free (current->directory);
  349.     free (current);
  350.     }
  351. }
  352.